package com.smproject.config;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
import java.util.Date;
import java.util.Map;

/**
 * 通过切面看见请求的日志
 * @author hu.liang
 * @Date 2018/10/13 0013
 */
@Aspect
@Order(2)
@Component
public class WebLogAspect {

    ThreadLocal<Long> startTime = new ThreadLocal();
    ThreadLocal<CommonLog> logThread = new ThreadLocal();

    private static Logger logger = LoggerFactory.getLogger(WebLogAspect.class);
    /**
     * 定义
     */
    @Pointcut("within(com.smproject.controller..*)")
    public void webLog(){}//定义一个切入点

    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint){
        this.startTime.set(System.currentTimeMillis());
        CommonLog logs = new CommonLog();
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        HttpServletResponse response = attributes.getResponse();
        logs.setCallTime(new Date());
        logs.setOptions(null);
        logs.setUrl(request.getRequestURL().toString());
        logs.setHttpMethod(request.getMethod());
        logs.setIp(request.getRemoteAddr());
        logs.setClassMethod(joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        if (joinPoint.getArgs().length > 0 && joinPoint.getArgs()[0] instanceof Serializable) {
            logs.setArgs(getParems(request));
        }
        this.logThread.set(logs);
        logger.info(logs.toString());
    }

    @AfterReturning(returning="rvt",pointcut = "webLog()")
    public void  doAfterReturning(JoinPoint joinPoint, Object rvt){
        CommonLog logs = (CommonLog)this.logThread.get();
        logs.setTime(System.currentTimeMillis() - ((Long)this.startTime.get()).longValue());
        if(rvt instanceof String){
            logs.setResult(rvt.toString());
        }else{
            logs.setResult(JSONUtil.parse(rvt).toString());
        }
        logger.info(logs.toString());
    }


    private String getParems(HttpServletRequest request){
        Map<String, String[]> param  = request.getParameterMap();
        JSONObject json = new JSONObject();
        for(Map.Entry<String,String[]> e : param.entrySet()){
            StringBuffer val = new StringBuffer();
            for(String  str : e.getValue()){
                val.append(str).append(",");
            }
            String newParam = val.toString().substring(0, val.length() - 1);
            json.put(e.getKey().toString(),newParam);
        }
        return json.toString();
    }


    @AfterThrowing(throwing="e",pointcut = "webLog() ")
    public void doAfterThrowing(JoinPoint joinPoint, Exception e) {
        CommonLog logs = (CommonLog)this.logThread.get();
        logs.setTime(System.currentTimeMillis() - ((Long)this.startTime.get()).longValue());
        logs.setResult(JSONUtil.toJsonStr(e));
        logger.info(logs.toString());
        this.startTime.remove();
        this.logThread.remove();
    }

}
